package com.gee.spring.cloud.feign.flow.binding;

import com.gee.spring.cloud.feign.flow.binding.exception.MethodNotFoundException;
import com.gee.spring.cloud.feign.flow.execute.ExecuteContext;
import com.gee.spring.cloud.feign.flow.execute.WorkExecuteDesigner;
import com.gee.spring.cloud.feign.flow.execute.WorkExecutor;
import com.gee.spring.cloud.feign.flow.util.FlowUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * desc:
 *
 * @author gee
 * @since 2021-03-31 10:24:59
 */
public class FeignFlowMethod {
    private static final Logger logger = LoggerFactory.getLogger(FeignFlowMethod.class);
    private Method method;
    private final BeanFactory beanFactory;
    private final ThreadPoolExecutor feignFlowThreadPoolExecutor;

    public FeignFlowMethod(Method method, BeanFactory beanFactory, ThreadPoolExecutor feignFlowThreadPoolExecutor) {
        this.method = method;
        this.beanFactory = beanFactory;
        this.feignFlowThreadPoolExecutor = feignFlowThreadPoolExecutor;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Object execute(Object target, Object[] args) throws MethodNotFoundException {
        Map<String, Object> argsMap = getArgsMap(args);
        ExecuteContext executeContext = ExecuteContext.Builder.build(argsMap, feignFlowThreadPoolExecutor);
        WorkExecuteDesigner designer = FlowUtil.getDesigner(method,beanFactory);

        return WorkExecutor.execute(executeContext, designer);
    }

    private Map<String, Object> getArgsMap(Object[] args){
        if (args == null || args.length == 0){
            return null;
        }
        Map<String, Object> argsMap = new HashMap<>();
        for (int i = 0; i < args.length; i++) {
            argsMap.put(String.valueOf(i + 1), args[i]);
        }
        return argsMap;
    }
}
